param(
	[Parameter(Mandatory=$False)]
	[string]$inputFile="inputlist.txt",						  # the input file to store vdi and fid list
	[switch]$inputFileSaved                                   # if inputlist.txt has been saved, if yes, it will run directly
)
Function Start-BulkThreads(){	# -Action { Stop-Process -Id $PID }
    param(
    	[Parameter(Mandatory=$True)]
    	[Object]$vdilist,               # the vdi list that scripts to be ran
    	[Parameter(Mandatory=$True)]    
    	[ScriptBlock]$Action,           # the actual action that each thread will run
    	[Parameter(Mandatory=$false)]   
    	[int]$maxCnt=100                # the default amount of powershell threads, if this number is big, then the system might get stuck
    )
	$results=@() # this is used to collect the result from each thread
	$vdiCounts = $vdilist.Count
	If( $vdiCounts -eq 1 ){ # no need to create thread pool to run it
		If( [string]::IsNullOrWhiteSpace($vdilist[0]) ){
		    write-error "vdilist only contains 1 line but it's null"
		}else{& $Action $vdilist[0] 1 $ActionParams}
	}else{
		$vdiCounts = $vdilist.Count ; $throttleLimit=$maxCnt ; If($vdiCounts -le $maxCnt ){$throttleLimit=$vdiCounts}
		# creaate the thread pool and run each thread based the vdi list amount
		$SessionState = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
		$Pool = [runspacefactory]::CreateRunspacePool(1, $throttleLimit, $SessionState, $Host)
		$Pool.Open() ; $threads = @() ; $cnt=1
		$handles = foreach($line in $vdilist){
			if( [string]::IsNullOrWhiteSpace($line ) ){continue}
			$powershell = [powershell]::Create().AddScript($Action).AddArgument($line).AddArgument($cnt)
			$powershell.RunspacePool = $Pool ;	$powershell.BeginInvoke() ; $threads += $powershell ; $cnt++
		}
		# wait each thread to be done and then collecte its return value
		do{
		  $i = 0 ;  $done = $true
		  foreach ($handle in $handles) {
			if($handle -ne $null){if($handle.IsCompleted){$results+=$threads[$i].EndInvoke($handle);$threads[$i].Dispose();$handles[$i]=$null}else{$done = $false}}
			$i++
		  }
		  if (-not $done) { Start-Sleep -Milliseconds 200 }
		} until ($done)
	}
	return $results # return the value collection from each thread and then export to csv or take other further actions
}
$this_path = Split-Path -Parent ($MyInvocation.MyCommand.Definition)
$this_user=$env:username
$this_machine=$env:computername
$inputlist=$null
#<-------------------------------- open inputlist.txt(create it if it not exists) and let user to enter the vdi list.
$inputFile="$this_path\$inputFile" ; If(!(test-path $inputFile )){new-item -ItemType File -Path $inputFile -force 1>$null}
$inputlist = get-content $inputFile |select -Unique|?{$_.trim() -ne ""}|sort
If( ($PSBoundParameters.ContainsKey('inputFileSaved') -and $inputlist.count -eq 0) -or !$inputFileSaved ){
	clear-content $inputFile -force -ErrorAction Ignore
	Do{ # loop above action if the vdi list is empty 
		write-host "Please save vdi(fid) list as below format in opened txt file each line as it's empty, please press 'Ctrl+C' if you want to quit:
		APACSGAWSBP0462,APAC
		LDNINTWVAQ0101,EMEA"; notepad $inputFile; read-host " "
		# get unique vdi name (exclude empty/blank spaces line)
		$inputlist = (get-content $inputFile |select -Unique|?{$_.trim() -ne ""}|sort)
	}While( $inputlist -eq $null  )
}

$action={
    param($line,$cnt)
	$vdi,$env=$line.split(",").ToUpper()
	write-host "Processing in $cnt-$vdi..."
	If(Test-Connection $vdi -quiet -count 1 -ea 0){
		return (Get-WmiObject win32_operatingsystem -cn $vdi| select @{n='Env';E={$env}}, @{n='VDI';e={$vdi}}, @{n='LastBootUpTime';e={[datetime]::ParseExact($_.lastbootuptime.Split('.')[0],"yyyyMMddHHmmss",$null)}})
	}else{
	    write-error "$vdi is offline"
	}
}
$rst=Start-BulkThreads $inputlist $action
$rst|Export-Csv -Path "$this_path\last_reboot_time.csv" -UseCulture -NoTypeInformation -Encoding UTF8 -Force -ErrorAction Ignore
write-host -ForegroundColor Yellow "VDI last reboot time has been saved in '$this_path\last_reboot_time.csv'"
